/*
 * @copyright: Huang Ding
 * @Author: ding-cx
 * @Date: 2021-08-16 11:01:16
 * @LastEditors: ding-cx
 * @LastEditTime: 2021-12-13 11:31:48
 * @Description: file content
 */

import * as egg from "egg";
import * as path from "path";
import * as fs from "fs";

const globby = require("globby");

export default class DingAppWorkerLoader extends egg.AgentWorkerLoader {
  // 加载模块中的定时任务
  loadModuleScheduleTask() {
    const importsModulesList: string[] = this.config?.modules?.imports || [];
    let match: string[] = [];

    if (importsModulesList.length > 0) {

      // note 此处拼接的路径，提供的模块名必须前后均无/ 如：正确：modName/abc      错误：/mod/aaa/
      const match1 = importsModulesList.map(item => {
        return "modules/" + item + "/**/task"
      })
      const match2 = importsModulesList.map(item => {
        return "modules/" + item + "/**/schedule"
      })
      match = [...match1, ...match2]
    } else {
      match = ["modules/**/task", "modules/**/schedule"];
    }

    let taskFilesDirs = globby.sync(match, {
      cwd: path.join(this.options.baseDir, "app"),
      onlyDirectories: true,
      onlyFiles: false,
    });


    this.options.logger.info("[dinegg] loader loadModuleScheduleTask task list %j", taskFilesDirs);
    for (const filePath of taskFilesDirs) {
      const fullPath = path.join(this.options.baseDir, "app", filePath);
      if (!fs.statSync(fullPath).isDirectory()) continue;
      this.config?.schedule?.directory?.push?.(fullPath); //把文件full path挂载在临时属性。在app.js中使用。
    }
  }
  // 加载模块的app.js/agent.js启动自定义引导文件。与egg的app.js相同。它在加载时实例化，然后在框架的同名生命周期钩子中执行。
  loadAppBoot() {
    const importsModulesList: string[] = this.config?.modules?.imports || [];
    let match: string[];
    if (importsModulesList.length === 0) {
      match = process.env.EGG_TYPESCRIPT === "true" ? ["**/agent.(js|ts)", "!**/*.d.ts"] : ["**/agent.js"];
    } else {
      match = importsModulesList.map((item) => {
        return process.env.EGG_TYPESCRIPT === "true" ? `${item}/**/agent.(js|ts)` : `${item}/**/agent.js`;
      });
      process.env.EGG_TYPESCRIPT === "true" && match.push("!**/*.d.ts");
    }

    const filePaths = globby.sync(match, {
      cwd: path.join(this.options.baseDir, "app/modules"),
    });
    // console.log(filePaths);
    this.options.logger.info("[dinegg] load app.js boot list: %j", filePaths);

    (this.app as any).__moduleExportAppBootInstanceList = filePaths.map((item) => {
      const bootClass = this.loadFile(path.join(this.options.baseDir, "app/modules", item));
      // 在启动自定义钩子方面，必须定义为class
      return new bootClass(this.app);
    });
  }
  /**
   * egg
   * 框架内原始的加载config
   */
  loadConfig() {
    this.loadPlugin();
    super.loadConfig();
  }

  load() {
    const isEnableModule = !!this.config?.modules?.enable;
    // 加载自定义app.js
    isEnableModule && this.loadAppBoot();

    isEnableModule && this.loadModuleScheduleTask();

    this.loadAgentExtend();
    this.loadContextExtend();

    this.loadCustomAgent();
  }
}
